package com.wkbb.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
public class BeanUtil extends BeanUtils {

	/**
	 * 将源对象中的值覆盖到目标对象中，仅覆盖源对象中不为NULL值的属性
	 * 
	 * @param dest
	 *            目标对象，标准的JavaBean
	 * @param orig
	 *            源对象，可为Map、标准的JavaBean
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static void applyIf(Object dest, Object orig) throws Exception {
		try {
			if (orig instanceof Map) {
				Iterator names = ((Map) orig).keySet().iterator();
				while (names.hasNext()) {
					String name = (String) names.next();
					if (PropertyUtils.isWriteable(dest, name)) {
						Object value = ((Map) orig).get(name);
						if (value != null) {
							PropertyUtils.setSimpleProperty(dest, name, value);
						}
					}
				}
			} else {
				java.lang.reflect.Field[] fields = orig.getClass().getDeclaredFields();
				for (int i = 0; i < fields.length; i++) {
					String name = fields[i].getName();
					if (PropertyUtils.isReadable(orig, name) && PropertyUtils.isWriteable(dest, name)) {
						Object value = PropertyUtils.getSimpleProperty(orig, name);
						if (value != null) {
							PropertyUtils.setSimpleProperty(dest, name, value);
						}
					}
				}
			}
		} catch (Exception e) {
			throw new Exception("将源对象中的值覆盖到目标对象中，仅覆盖源对象中不为NULL值的属性", e);
		}
	}

	/**
	 * 将源对象中的值覆盖到目标对象中，仅覆盖源对象中不为NULL值的属性
	 * 
	 * @param orig
	 *            源对象，标准的JavaBean
	 * @param dest
	 *            排除检查的属性，Map
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static boolean checkObjProperty(Object orig, Map dest) throws Exception {
		try {
			java.lang.reflect.Field[] fields = orig.getClass().getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				String name = fields[i].getName();
				if (!dest.containsKey(name)) {
					if (PropertyUtils.isReadable(orig, name)) {
						Object value = PropertyUtils.getSimpleProperty(orig, name);
						if (value == null) {
							return true;
						}
					}
				}
			}
			return false;
		} catch (Exception e) {
			throw new Exception("将源对象中的值覆盖到目标对象中，仅覆盖源对象中不为NULL值的属性", e);
		}
	}

	/**
	 * 反射copy集合对象
	 * @param sourceList 源数据列表
	 * @param clazz 目标类型
	 * @return 封装后的列表
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public static <L,R> List<R> copyPropertiesList(List<L> sourceList, Class<R> clazz) throws IllegalAccessException, InstantiationException {
		if(sourceList == null || sourceList.size() == 0){return new ArrayList<>();}

		List<R> list = new ArrayList<>();
		for(L source : sourceList){
			R obj = clazz.newInstance();
			org.springframework.beans.BeanUtils.copyProperties(source, obj);
			list.add(obj);
		}
		return list;
	}

	/**
	 * 反射copy一个对象
	 * @param source 源数据
	 * @param target 目标
	 * @return 转换后的对象
	 */
	public static <L,R> R copyProperties(L source, Class<R> target){
		if(source == null || target == null){return null;}
		R targetObj;
		try {
			targetObj = target.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			log.info("javaBean转换出错，{},MSG:{}",source,e);
			e.printStackTrace();
			return null;
		}
		org.springframework.beans.BeanUtils.copyProperties(source, targetObj);
		return targetObj;
	}
}
